package com.ygqh.baby.service.impl;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.ygqh.baby.po.YgUser;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ygqh.baby.ao.Constant;
import com.ygqh.baby.ao.CustomerStatus;
import com.ygqh.baby.ao.DataStatus;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.OrderDirection;
import com.ygqh.baby.ao.QueryInfo;
import com.ygqh.baby.ao.ResultSet;
import com.ygqh.baby.dao.CustomerUserDao;
import com.ygqh.baby.model.ChatRecord;
import com.ygqh.baby.model.CustomerUser;
import com.ygqh.baby.model.YgUserModel;
import com.ygqh.baby.service.ChatRecordService;
import com.ygqh.baby.service.CustomerUserService;
import com.ygqh.baby.service.YgUserService;

/**
 * @author Ss
 */
@Service
public class CustomerUserServiceImpl implements CustomerUserService {

	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private final ExecutorService executorService = Executors.newFixedThreadPool(3);

	@Autowired
	private CustomerUserDao customerUserDao;
	@Autowired
	private ChatRecordService chatRecordService;
	@Autowired
	private YgUserService ygUserService;

	@Override
	public void save(CustomerUser customerUser) {
		customerUserDao.saveEntity(customerUser);
	}

	@Override
	public void updateEntity(CustomerUser customerUser) {
		customerUserDao.updateEntity(customerUser);
	}

	@Override
	public CustomerUser findUserById(String id) {
		return customerUserDao.findEntityById(id);
	}

	@Override
	public CustomerUser findByUserName(String username) {
		if (StringUtils.isBlank(username)) {
			return null;
		}
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("userName", username);
		conditions.put("status", DataStatus.Valid);
		List<CustomerUser> entityList = customerUserDao.getEntityList(conditions, null);
		if (CollectionUtils.isNotEmpty(entityList)) {
			return entityList.get(0);
		}
		return null;
	}

	@Override
	public Message updateCustomerStatus(String userName, CustomerStatus customerStatus) {
		if (StringUtils.isBlank(userName) || customerStatus == null) {
			return Message.error(Constant.TRY_AGAIN_LATER);
		}
		Map<String, Object> updateMap = new HashMap<>();
		updateMap.put("customerStatus", customerStatus);
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("userName", userName);
		customerUserDao.updateEntities(updateMap, conditions);
		return Message.success(1);
	}

	@Override
	public Message distributionCustomerToUser(YgUserModel ygUser, String onlineCustomerId) {
		if (ygUser == null) {
			return Message.error(Constant.TRY_AGAIN_LATER);
		}
		List<String> onlineCustomerIds = getCustomerIds(onlineCustomerId);
		if (onlineCustomerIds != null && onlineCustomerIds.size() == 0) {
			return Message.success(null);
		}
		List<CustomerUser> entityList = findCustomerUserList(ygUser.getId());
		if (CollectionUtils.isNotEmpty(entityList)) {
			//熟人
			return validateAcquaintances(entityList.get(0), ygUser, onlineCustomerIds);
		}
		entityList = this.findCustomerList(null, Boolean.FALSE, CustomerStatus.Online);
		if (CollectionUtils.isEmpty(entityList)) {
			return Message.success(null);
		}
		validateCustomerUser(entityList, onlineCustomerIds);
		if (CollectionUtils.isEmpty(entityList)) {
			return Message.success(null);
		}
		CustomerUser customerUser = entityList.get(0);
		customerUser.getUserList().addFirst(ygUser);
		customerUser.getUserIdList().addFirst(ygUser.getId());
		this.updateEntity(customerUser);
		return Message.success(customerUser);
	}
	
	private List<String> getCustomerIds(String onlineCustomerId) {
		if (onlineCustomerId == null) {
			return null;
		} else if ("".equals(onlineCustomerId)) {
			return new ArrayList<>();
		}
		String[] split = onlineCustomerId.split("[,，]");
		if (split.length == 0) {
			return null;
		}
		List<String> customerIds = new ArrayList<>();
		for (String string : split) {
			if (StringUtils.isBlank(string)) {
				continue;
			}
			customerIds.add(string);
		}
		return customerIds;
	}

	private void updateToOfflineWithIds(List<String> customerIds) {
		if (CollectionUtils.isEmpty(customerIds)) {
			return;
		}
		logger.info("前台客服在线信息和数据库不一致，触发更新操作，customerIds={}", customerIds);
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("id", customerIds);
		Map<String, Object> updateMap = new HashMap<>();
		updateMap.put("customerStatus", CustomerStatus.Offline);
		customerUserDao.updateEntities(updateMap , conditions);
	}

	private Message validateAcquaintances(CustomerUser customerUser, YgUserModel user, List<String> onlineCustomerIds) {
		// 更新客服下的用户信息
		updateYgUserInfo(customerUser, user);
		if (!customerUser.getCustomerStatus().equals(CustomerStatus.Offline) 
				&& (onlineCustomerIds == null || onlineCustomerIds.contains(customerUser.getId()))) {
			//熟人在线
			this.updateEntity(customerUser);
			return Message.success(customerUser);
		}
		//熟人不在线
		List<CustomerUser> entityList = this.findCustomerList(customerUser.getUserName(), Boolean.FALSE, CustomerStatus.Online);
		if (CollectionUtils.isEmpty(entityList)) {
			return Message.success(null);
		}
		validateCustomerUser(entityList, onlineCustomerIds);
		if (CollectionUtils.isEmpty(entityList)) {
			return Message.success(null);
		}
		CustomerUser newCustomerUser = entityList.get(0);
		this.changeUserInfoFromOldToNew(customerUser, newCustomerUser, user.getId());
		return Message.success(newCustomerUser);
	}
	
	private CustomerUser updateYgUserInfo(CustomerUser customerUser, YgUserModel user) {
		if (!customerUser.getUserIdList().contains(user.getId())) {
			return customerUser;
		}
		Iterator<YgUserModel> iterator = customerUser.getUserList().iterator();
		while (iterator.hasNext()) {
			YgUserModel oldUser = iterator.next();
			if (oldUser.getId().compareTo(user.getId()) == 0) {
				user.setIsStar(oldUser.getIsStar());
				iterator.remove();
				break;
			}
		}
		customerUser.getUserList().add(user);
		return customerUser;
	}

	private void validateCustomerUser(List<CustomerUser> entityList, List<String> onlineCustomerIds) {
		if (onlineCustomerIds == null) {
			return;
		}
		List<String> offlineList = new ArrayList<>();
		Iterator<CustomerUser> iterator = entityList.iterator();
		while (iterator.hasNext()) {
			CustomerUser customerUser = iterator.next();
			if (!onlineCustomerIds.contains(customerUser.getId())) {
				offlineList.add(customerUser.getId());
				iterator.remove();
			}
		}
		executorService.execute(() -> updateToOfflineWithIds(offlineList));
	}

	private List<CustomerUser> findCustomerUserList(Long userId) {
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("userIdList", Collections.singletonList(userId));
		List<CustomerUser> entityList = customerUserDao.getEntityList(conditions, null);
		if (CollectionUtils.isEmpty(entityList)) {
			return new ArrayList<>();
		}
		return entityList;
	}

	@Override
	public void updateCustomerWithUser(CustomerUser customerUser, YgUserModel ygUser) {
		for (YgUserModel user : customerUser.getUserList()) {
			if (user.getId().equals(ygUser.getId())) {
				customerUser.getUserList().remove(user);
				customerUser.getUserList().addFirst(ygUser);
				break;
			}
		}
		this.updateEntity(customerUser);
	}

	@Override
	public List<CustomerUser> findCustomerList(String userName, Boolean isDefault, CustomerStatus customerStatus) {
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("status", DataStatus.Valid);
		if (StringUtils.isNotBlank(userName)) {
			Map<String, Object> map = new HashMap<>();
			map.put("userName", userName);
			conditions.put("ne", map);
		}
		if (isDefault != null) {
			conditions.put("isDefault", isDefault);
		} 
		if (customerStatus != null) {
			conditions.put("customerStatus", customerStatus);
		}
		List<CustomerUser> entityList = customerUserDao.getEntityList(conditions, null);
		if (entityList == null) {
			return new ArrayList<>();
		}
		//以接待用户数升序排序
		entityList.sort((o1, o2) -> {
			Long userCount1 = 0L;
			if (o1.getUserList() != null) {
				userCount1 = o1.getUserList().stream().filter(YgUserModel::getIsOnline).count();
			}
			Long userCount2 = 0L;
			if (o2.getUserList() != null) {
				userCount2 = o2.getUserList().stream().filter(YgUserModel::getIsOnline).count();
			}
			return userCount1.compareTo(userCount2);
		});
		return entityList;
	}

	@Override
	public Message updateUserToOtherCustomer(String currentCustomerId, String transCustomerId, Long userId) {
		CustomerUser currentCustomer = this.findUserById(currentCustomerId);
		CustomerUser transCustomer = this.findUserById(transCustomerId);
		changeUserInfoFromOldToNew(currentCustomer, transCustomer, userId);
		return Message.success(transCustomer);
	}
	
	private void changeUserInfoFromOldToNew(CustomerUser currentCustomer, CustomerUser transCustomer, Long userId) {
		if (currentCustomer.getIsDefault()) {
			// 留言客服
			List<CustomerUser> list = this.findCustomerUserList(userId);
			if (CollectionUtils.isEmpty(list)) {
				YgUserModel userModel = ygUserService.findModelById(userId);
				userModel.setIsStar(Boolean.TRUE);
				transCustomer.getUserIdList().addFirst(userId);
				transCustomer.getUserList().addFirst(userModel);
				this.updateEntity(transCustomer);
				return;
			}
			currentCustomer = list.get(0);
		}
		if (currentCustomer.getId().equals(transCustomer.getId())) {
			return;
		}
		currentCustomer.getUserIdList().remove(userId);
		transCustomer.getUserIdList().addFirst(userId);
		Iterator<YgUserModel> iterator = currentCustomer.getUserList().iterator();
		while (iterator.hasNext()) {
			YgUserModel next = iterator.next();
			if (next.getId().equals(userId)) {
				iterator.remove();
				transCustomer.getUserList().addFirst(next);
				break;
			}
		}
		this.updateEntity(currentCustomer);
		this.updateEntity(transCustomer);
	}

	@Override
	public Message updateUserByIsStar(String customerId, Long userId, Boolean isStar) {
		if (userId == null || isStar == null) {
			return Message.error(Constant.TRY_AGAIN_LATER, null);
		}
		CustomerUser customerUser;
		if (StringUtils.isNotBlank(customerId)) {
			customerUser = this.findUserById(customerId);
		} else {
			List<CustomerUser> customerUserList = this.findCustomerUserList(userId);
			if (CollectionUtils.isEmpty(customerUserList)) {
				return Message.error("数据异常，请刷新重试", null);
			}
			customerUser = customerUserList.get(0);
		}
		for (YgUserModel user : customerUser.getUserList()) {
			if (user.getId().equals(userId)) {
				user.setIsStar(isStar);
				break;
			}
		}
		this.updateEntity(customerUser);
		return Message.success(1);
	}

	@Override
	public ResultSet<CustomerUser> searchCustomerUser(QueryInfo queryInfo, String nickName, CustomerStatus customerStatus, DataStatus status) {
		List<CustomerUser> userList = this.findCustomerList(queryInfo, nickName, customerStatus, status);
		Long count = this.customerCount(nickName, customerStatus, status);
		return new ResultSet<>(count, userList);
	}

	private Long customerCount(String nickName, CustomerStatus customerStatus, DataStatus status) {
		Map<String, Object> conditions = new HashMap<>();
		if (StringUtils.isNotBlank(nickName)) {
			conditions.put("nickName", "^.*" + nickName + ".*$");
		}
		if (customerStatus != null) {
			conditions.put("customerStatus", customerStatus);
		}
		if (status != null) {
			conditions.put("status", status);
		} else {
			conditions.put("status", DataStatus.Valid);
		}
		return customerUserDao.getEntityCount(conditions);
	}

	@Override
	public List<CustomerUser> findCustomerList(QueryInfo queryInfo, String nickName, CustomerStatus customerStatus, DataStatus status) {
		Map<String, Object> conditions = new HashMap<>();
		if (StringUtils.isNotBlank(nickName)) {
			conditions.put("nickName", "^.*" + nickName + ".*$");
		}
		if (customerStatus != null) {
			conditions.put("customerStatus", customerStatus);
		}
		if (status != null) {
			conditions.put("status", status);
		} else {
			conditions.put("status", DataStatus.Valid);
		}
		Map<String, String> orders = new HashMap<>();
		orders.put("createTime", OrderDirection.desc.name());
		return customerUserDao.getPageEntityList(queryInfo, conditions, orders);
	}

	@Override
	public CustomerUser validateCustomer(String customerId, YgUserModel ygUser) {
		if (StringUtils.isNotBlank(customerId)) {
			CustomerUser customerUser = this.findUserById(customerId);
			if (!customerUser.getCustomerStatus().equals(CustomerStatus.Offline)) {
				this.updateCustomerWithUser(customerUser, ygUser);
				return customerUser;
			}
		}
		//所有客服不在线，发给处理留言人
		return findCustomerByDefault();
	}

	@Override
	public CustomerUser findCustomerByDefault() {
		List<CustomerUser> findCustomerList = this.findCustomerList(null, Boolean.TRUE, null);
		if (CollectionUtils.isNotEmpty(findCustomerList)) {
			return findCustomerList.get(0);
		}
		return null;
	}

	@Override
	public Message updateCustomerUserByStatus(String id, DataStatus status) {
		if (StringUtils.isBlank(id) || status == null) {
			return Message.error(Constant.TRY_AGAIN_LATER);
		}
		Map<String, Object> updateMap = new HashMap<>();
		updateMap.put("status", status);
		customerUserDao.updateEntity(updateMap , id);
		return Message.success(1);
	}

	@Override
	public List<YgUserModel> findUserList(String q, CustomerUser customerUser) {
		List<YgUserModel> userList = findUserList(customerUser);
		if (StringUtils.isBlank(q)) {
			return userList;
		}
		
		//模糊搜索
		List<YgUserModel> searchUserList = userList.parallelStream()
				.filter(o -> (o.getNickName().contains(q)))
				.collect(Collectors.toList());
		
		List<Long> userIdList = userList.stream().map(YgUserModel::getId).collect(Collectors.toList());
		//获取用户集的聊天记录
		List<ChatRecord> recordList = chatRecordService.findUserRecordList(userIdList, q);
		if (CollectionUtils.isEmpty(recordList)) {
			return searchUserList;
		}
		
		//按用户id分组
		Map<Long, List<ChatRecord>> groupByUserIdMap = recordList.parallelStream().collect(Collectors.groupingBy(ChatRecord::getUserId));
		if (MapUtils.isEmpty(groupByUserIdMap)) {
			return searchUserList;
		}
		for (YgUserModel user : userList) {
			if (!groupByUserIdMap.containsKey(user.getId())) {
				//过滤没有聊天记录的用户
				continue;
			}
			if (!searchUserList.contains(user)) {
				//去重
				searchUserList.add(user);
			}
		}
		return searchUserList;
	}
	
	/**
	 * 获取客服下的用户集
	 * @param customerUser
	 * @return
	 */
	@Override
	public List<YgUserModel> findUserList(CustomerUser customerUser) {
		List<YgUserModel> userList = new ArrayList<>();
		if (customerUser != null) {
			//获取指定客服的用户集
			if (customerUser.getIsDefault()) {
				//留言客服
				userList.addAll(findUserListByDefault(customerUser));
			} else {
				userList.addAll(customerUser.getUserList());
			}
		} else {
			userList.addAll(findUserListByAllCustomer());
		}
		//用户集排序
		sortUserList(userList);
		return userList;
	}

	/**
	 * 获取所有客服的用户集
	 */
	private List<YgUserModel> findUserListByAllCustomer() {
		List<YgUserModel> userList = new ArrayList<>();
		//获取所有客服的用户集
		List<CustomerUser> customerUserList = this.findCustomerList(null, Boolean.FALSE, null);
		customerUserList.forEach(o -> userList.addAll(o.getUserList()));
		return userList;
	}
	
	/**
	 * 获取留言客服下的用户集(以聊天记录为基准查询)
	 * @return
	 */
	private List<YgUserModel> findUserListByDefault(CustomerUser customerUser) {
		if (customerUser == null) {
			customerUser = findCustomerByDefault();
		}
		//获取所有未读留言
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("receiveUserId", customerUser.getId());
		conditions.put("isRead", Boolean.FALSE);
		conditions.put("status", DataStatus.Valid);
		List<ChatRecord> chatRecords = chatRecordService.findUserRecordList(conditions, null);
		return new ArrayList<>(findUserListByChatRecord(chatRecords, null));
	}

	private List<YgUserModel> findUserListByChatRecord(List<ChatRecord> chatRecords, String q) {
		List<YgUserModel> userList = new ArrayList<>();
		if (CollectionUtils.isEmpty(chatRecords)) {
			return userList;
		}
		Map<Long, List<ChatRecord>> collect = chatRecords.parallelStream().collect(Collectors.groupingBy(ChatRecord::getUserId));
		if (MapUtils.isEmpty(collect)) {
			return userList;
		}
		//获取所有客服下的用户集
		List<YgUserModel> userListByAllCustomer = findUserListByAllCustomer();
		
		List<Long> existsUserIdList = new ArrayList<>();
		if (StringUtils.isNotBlank(q)) {
			//模糊搜索昵称
			List<YgUserModel> searchUserList = userListByAllCustomer.parallelStream()
					.filter(o -> (o.getNickName().contains(q)))
					.collect(Collectors.toList());
			if (CollectionUtils.isNotEmpty(searchUserList)) {
				userList.addAll(searchUserList);
			}
			List<Long> list = searchUserList.stream().map(YgUserModel::getId).collect(Collectors.toList());
			existsUserIdList.addAll(list);
		}
		
		Map<Long, List<YgUserModel>> collect2 = userListByAllCustomer.parallelStream().collect(Collectors.groupingBy(YgUserModel::getId));
		
		List<Long> outcludeUserIdList = new ArrayList<>();
		collect.forEach((userId, chatRecordList) -> {
			if (existsUserIdList.contains(userId)) {
				return;
			}
			if (MapUtils.isNotEmpty(collect2) && collect2.containsKey(userId)) {
				//所有客服下的用户集包含当前用户（在线用户或者被客服标星用户）
				userList.add(collect2.get(userId).get(0));
			} else {
				outcludeUserIdList.add(userId);
			}
		});
		if (CollectionUtils.isNotEmpty(outcludeUserIdList)) {
			List<YgUserModel> outcludeUserList = ygUserService.findModelByIds(outcludeUserIdList);
			userList.addAll(outcludeUserList);
		}
		return userList;
	}

	/**
	 * 用户集排序
	 * @param userList
	 */
	private void sortUserList(List<YgUserModel> userList) {
		//以是否为星标用户排序
		userList.sort((o1, o2) -> o2.getIsStar().compareTo(o1.getIsStar()));
		//以是否在线排序
		userList.sort((o1, o2) -> o2.getIsOnline().compareTo(o1.getIsOnline()));
	}

	@Override
	public CustomerUser isExistsByUserName(String userName, String id) {
		if (StringUtils.isBlank(userName)) {
			return null;
		}
		Map<String, Object> conditions = new HashMap<>();
		conditions.put("userName", userName);
		if (StringUtils.isNotBlank(id)) {
			Map<String, Object> map = new HashMap<>();
			map.put("id", id);
			conditions.put("ne", map);
		}
		List<CustomerUser> entityList = customerUserDao.getEntityList(conditions, null);
		if (CollectionUtils.isNotEmpty(entityList)) {
			return entityList.get(0);
		}
		return null;
	}

	@Override
	public void updateCustomerWithLogout(String userName) {
		if (StringUtils.isBlank(userName)) {
			return;
		}
		CustomerUser customer = this.findByUserName(userName);
		customer.setCustomerStatus(CustomerStatus.Offline);
		LinkedList<YgUserModel> userList = customer.getUserList();
		Iterator<YgUserModel> itr = userList.iterator();
		while (itr.hasNext()) {
			YgUserModel user = itr.next();
			if (!user.getIsStar()) {
				customer.getUserIdList().remove(user.getId());
				itr.remove();
			}
		}
		customer.setUserList(userList);
		customerUserDao.updateEntity(customer);
	}

	@Override
	public void updateUserByIsOnline(Long userId, Boolean isOnline) {
		if (userId == null || isOnline == null) {
			return;
		}
		List<CustomerUser> entityList = findCustomerUserList(userId);
		if (CollectionUtils.isEmpty(entityList)) {
			return;
		}
		CustomerUser customerUser = entityList.get(0);
		for (YgUserModel user : customerUser.getUserList()) {
			if (user.getId().equals(userId)) {
				user.setIsOnline(isOnline);
				break;
			}
		}
		this.updateEntity(customerUser);
	}

	@Override
	public List<YgUserModel> searchUserList(String q) {
		List<YgUserModel> userList = new ArrayList<>();
		if (StringUtils.isBlank(q)) {
			return userList;
		}
		YgUser ygUser = ygUserService.findByUserName(q);
		List<ChatRecord> recordList;
		if (ygUser == null) {
			// 模糊查询聊天记录
			recordList = chatRecordService.findUserRecordList(null, q);
		} else {
			recordList = chatRecordService.findUserRecordList(Collections.singletonList(ygUser.getId()), null);
		}
		userList.addAll(findUserListByChatRecord(recordList, q));
		return userList;
	}

	@Override
	public List<YgUserModel> findUserListByIsStar(Boolean isStar) {
		List<YgUserModel> userListByAllCustomer = this.findUserListByAllCustomer();
		if (CollectionUtils.isEmpty(userListByAllCustomer)) {
			return new ArrayList<>();
		}
		List<YgUserModel> userList;
		if (isStar != null && isStar) {
			userList = userListByAllCustomer.stream().filter(YgUserModel::getIsStar).collect(Collectors.toList());
		} else {
			userList = userListByAllCustomer;
		}
		//用户集排序
		sortUserList(userList);
		return userList;
	}

	@Override
	public Message deleteUserFromCustomer(Long[] userIds, String customerUserName) {
		CustomerUser customerUser = this.findByUserName(customerUserName);
		LinkedList<YgUserModel> userList = customerUser.getUserList();
		LinkedList<Long> userIdList = customerUser.getUserIdList();
		List<Long> userIdListForDel = Arrays.asList(userIds);
		Iterator<YgUserModel> iterator = userList.iterator();
		while (iterator.hasNext()) {
			YgUserModel userModel = iterator.next();
			if (userIdListForDel.contains(userModel.getId())) {
				iterator.remove();
				userIdList.remove(userModel.getId());
			}
		}
		customerUser.setUserList(userList);
		customerUser.setUserIdList(userIdList);
		this.updateEntity(customerUser);
		return Message.success(null);
	}

}
